/**
 * Axios HTTP 请求封装
 * 统一处理请求拦截、响应拦截、错误处理
 */

import axios from 'axios'
import { ElMessage, ElLoading } from 'element-plus'
import { useAuthStore } from '@/stores/auth'
import router from '@/router'

// 创建 axios 实例
const service = axios.create({
    baseURL: import.meta.env.VITE_API_BASE_URL, // API 基础路径
    timeout: 150000, // 请求超时时间 15秒
    headers: {
        'Content-Type': 'application/json;charset=UTF-8'
    }
})

// 请求加载实例
let loadingInstance = null
// 当前请求数量
let requestCount = 0

/**
 * 显示加载动画
 */
function showLoading() {
    if (requestCount === 0) {
        loadingInstance = ElLoading.service({
            lock: true,
            text: '加载中...',
            background: 'rgba(0, 0, 0, 0.7)'
        })
    }
    requestCount++
}

/**
 * 隐藏加载动画
 */
function hideLoading() {
    requestCount--
    if (requestCount === 0 && loadingInstance) {
        loadingInstance.close()
        loadingInstance = null
    }
}

/**
 * 请求拦截器
 */
service.interceptors.request.use(
    (config) => {
        // 显示加载动画（可配置是否显示）
        if (config.loading !== false) {
            showLoading()
        }

        // 获取 token
        const authStore = useAuthStore()
        if (authStore.token) {
            // 在请求头中添加 token（多种格式，兼容不同后端）
            config.headers['Authorization'] = `Bearer ${authStore.token}`
            config.headers['token'] = authStore.token
            config.headers['X-Token'] = authStore.token
        }

        // 处理 GET 请求参数，过滤空值
        if (config.method === 'get' && config.params) {
            config.params = filterEmptyParams(config.params)
        }

        // 打印请求信息（开发环境）
        if (import.meta.env.DEV) {
            console.log('📤 请求:', config.method?.toUpperCase(), config.url, config.params || config.data)
        }

        return config
    },
    (error) => {
        hideLoading()
        console.error('❌ 请求错误:', error)
        ElMessage.error('请求配置错误')
        return Promise.reject(error)
    }
)

/**
 * 响应拦截器
 */
service.interceptors.response.use(
    (response) => {
        hideLoading()

        // 如果是文件下载（blob），直接返回response.data
        if (response.config.responseType === 'blob') {
            return response.data
        }

        const res = response.data

        // 打印响应信息（开发环境）
        if (import.meta.env.DEV) {
            console.log('📥 响应:', response.config.url, res)
        }

        // 根据后端返回的状态码进行处理
        // 这里假设后端返回格式为: { code: 200, data: {}, message: '' }
        const code = res.code || response.status

        // 成功
        if (code === 200 || code === 0) {
            return res
        }

        // Token 过期或无效
        if (code === 401) {
            ElMessage.error(res.message || '登录已过期，请重新登录')
            const authStore = useAuthStore()
            authStore.logout()
            router.push({
                path: '/login',
                query: { redirect: router.currentRoute.value.fullPath }
            })
            return Promise.reject(new Error(res.message || '未授权'))
        }

        // 权限不足
        if (code === 403) {
            ElMessage.error(res.message || '权限不足，无法访问')
            return Promise.reject(new Error(res.message || '权限不足'))
        }

        // 资源不存在
        if (code === 404) {
            ElMessage.error(res.message || '请求的资源不存在')
            return Promise.reject(new Error(res.message || '资源不存在'))
        }

        // 服务器错误
        if (code >= 500) {
            ElMessage.error(res.message || '服务器错误，请稍后重试')
            return Promise.reject(new Error(res.message || '服务器错误'))
        }

        // 其他错误
        ElMessage.error(res.message || '请求失败')
        return Promise.reject(new Error(res.message || '请求失败'))
    },
    (error) => {
        hideLoading()

        console.error('❌ 响应错误:', error)

        // 处理网络错误
        if (error.message === 'Network Error') {
            ElMessage.error('网络连接失败，请检查网络设置')
            return Promise.reject(error)
        }

        // 处理超时
        if (error.code === 'ECONNABORTED' || error.message.includes('timeout')) {
            ElMessage.error('请求超时，请稍后重试')
            return Promise.reject(error)
        }

        // 处理 HTTP 状态码错误
        if (error.response) {
            const status = error.response.status
            const message = error.response.data?.message || '请求失败'

            switch (status) {
                case 401:
                    ElMessage.error('登录已过期，请重新登录')
                    const authStore = useAuthStore()
                    authStore.logout()
                    router.push({
                        path: '/login',
                        query: { redirect: router.currentRoute.value.fullPath }
                    })
                    break
                case 403:
                    ElMessage.error('权限不足，无法访问')
                    break
                case 404:
                    ElMessage.error('请求的资源不存在')
                    break
                case 500:
                    ElMessage.error('服务器错误，请稍后重试')
                    break
                default:
                    ElMessage.error(message)
            }
        } else {
            ElMessage.error(error.message || '请求失败')
        }

        return Promise.reject(error)
    }
)

/**
 * 过滤空参数
 * @param {Object} params 参数对象
 * @returns {Object} 过滤后的参数对象
 */
function filterEmptyParams(params) {
    const result = {}
    Object.keys(params).forEach((key) => {
        const value = params[key]
        if (value !== null && value !== undefined && value !== '') {
            result[key] = value
        }
    })
    return result
}

/**
 * 封装 GET 请求
 * @param {String} url 请求地址
 * @param {Object} params 请求参数
 * @param {Object} config 额外配置
 * @returns {Promise}
 */
export function get(url, params = {}, config = {}) {
    return service({
        method: 'get',
        url,
        params,
        ...config
    })
}

/**
 * 封装 POST 请求
 * @param {String} url 请求地址
 * @param {Object} data 请求数据
 * @param {Object} config 额外配置
 * @returns {Promise}
 */
export function post(url, data = {}, config = {}) {
    return service({
        method: 'post',
        url,
        data,
        ...config
    })
}

/**
 * 封装 PUT 请求
 * @param {String} url 请求地址
 * @param {Object} data 请求数据
 * @param {Object} config 额外配置
 * @returns {Promise}
 */
export function put(url, data = {}, config = {}) {
    return service({
        method: 'put',
        url,
        data,
        ...config
    })
}

/**
 * 封装 DELETE 请求
 * @param {String} url 请求地址
 * @param {Object} params 请求参数
 * @param {Object} config 额外配置
 * @returns {Promise}
 */
export function del(url, params = {}, config = {}) {
    return service({
        method: 'delete',
        url,
        params,
        ...config
    })
}

/**
 * 封装文件上传
 * @param {String} url 上传地址
 * @param {FormData} formData 表单数据
 * @param {Function} onUploadProgress 上传进度回调
 * @returns {Promise}
 */
export function upload(url, formData, onUploadProgress) {
    return service({
        method: 'post',
        url,
        data: formData,
        headers: {
            'Content-Type': 'multipart/form-data'
        },
        onUploadProgress,
        timeout: 60000 // 上传超时时间 60秒
    })
}

/**
 * 封装文件下载
 * @param {String} url 下载地址
 * @param {Object} params 请求参数
 * @param {String} filename 文件名
 * @returns {Promise}
 */
export function download(url, params = {}, filename = '') {
    return service({
        method: 'get',
        url,
        params,
        responseType: 'blob',
        timeout: 60000, // 下载超时时间 60秒
        loading: false  // 文件下载不显示全局loading
    }).then((response) => {
        // 创建下载链接
        const blob = new Blob([response])
        const downloadUrl = window.URL.createObjectURL(blob)
        const link = document.createElement('a')
        link.href = downloadUrl

        // 设置文件名
        if (filename) {
            link.download = filename
        } else {
            // 从响应头获取文件名
            const contentDisposition = response.headers?.['content-disposition']
            if (contentDisposition) {
                const filenameMatch = contentDisposition.match(/filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/)
                if (filenameMatch && filenameMatch[1]) {
                    link.download = decodeURIComponent(filenameMatch[1].replace(/['"]/g, ''))
                }
            }
        }

        // 触发下载
        document.body.appendChild(link)
        link.click()
        document.body.removeChild(link)

        // 释放 URL 对象
        window.URL.revokeObjectURL(downloadUrl)

        return response
    })
}

// 导出 axios 实例，供特殊场景使用
export default service

